<?php
	defined( '_JEXEC' ) or die( 'Restricted access' );
	jimport( 'joomla.application.component.model' );
	jimport( 'joomla.methods' );
	include_once(JPATH_COMPONENT.DS.'libraries'.DS.'core.php');
	require_once(JPATH_COMPONENT.DS.'data'.DS.'implFusionTables'.DS.'FTDAOFactory.php');
	require_once(JPATH_COMPONENT.DS.'data'.DS.'implJoomla'.DS.'JDAOFactory.php');
	require_once(JPATH_COMPONENT.DS.'dominio'.DS.'DTOFactory.php');
	
	class ModelSocialRoutesRoute extends JModel
	{
		var $_route = null;
		
		var $_route1 = null;
		var $_route2 = null;
		var $_route1Click = null;
		var $_route2Click = null;
		var $_r3=false;
		
		//General
		var $_route3 = null;
		
		//Nuevas
		var $_route4 = null;
		var $_route5 = null;
		var $_route4Click = null;
		var $_route5Click = null;
		
		
		var $_interseccion = 0;
	
	
		
		function __construct()
		{
			parent::__construct();
		}
		
		private function addCreateRouteSocialActivity($route){
			$act = new stdClass();
			$act->cmd = 'route.create';
			$act->actor = $route->getUser()->get('id');
			$act->target = 0; // no target
			$act->title = JText::sprintf('CC ROUTE CREATED',JRoute::_('index.php?option=' . JRequest::getCmd('option') .'&task=showRoute&id=' . $route->getId()),$route->getName());
			$act->content = JText::sprintf('CC ROUTE DETAILS',$route->getDistance(),$route->getTime());
			$act->app = 'profile';
			$act->cid = 0;
			
			CFactory::load('libraries', 'activities');
			CActivityStream::add($act);
		}
		
		private function addUploadRouteSocialActivity($route){
			$act = new stdClass();
			$act->cmd = 'route.upload';
			$act->actor = $route->getUser()->get('id');
			$act->target = 0; // no target
			$act->title = JText::sprintf('CC ROUTE UPLOADED',JRoute::_('index.php?option=' . JRequest::getCmd('option') .'&task=showRoute&id=' . $route->getId()),$route->getName());
			$act->content = JText::sprintf('CC ROUTE DETAILS',$route->getDistance(),$route->getTime());
			$act->app = 'profile';
			$act->cid = 0;
			
			CFactory::load('libraries', 'activities');
			CActivityStream::add($act);
		}
		
		private function getIsMyRoute($route){
			$daoUserRoutes=JDAOFactory::getInstance()->getDAOUserRoutes();
			$userRoutes=$daoUserRoutes->getUserRoutes(JFactory::getUser()->get('id'));
			
			$i=0;
			$end=false;
			while(!$end && $i<count($userRoutes)){
				if($userRoutes[$i]->getRouteId() == $route->getId()){
					$end=true;
				}
				$i++;
			}
			return $end;
		}
		
		public function getIsCreator($route){
			if($route->getUser()->get('id')==JFactory::getUser()->get('id')){
				return true;
			}
			return false;
		}
		
		//Sets the route from the DB by using the id in the request
		function readRoute($id){
			$daoJRoute=JDAOFactory::getInstance()->getDAORoute();
			$this->_route=$daoJRoute->getRoute($id);
			return $this->_route;
		}
		
		//Sets and saves the route that comes in the request
		function saveRouteFromRequest(){
			$this->_route=DTOFactory::getInstance()->getDTORouteFromRequest();
			
			$daoRoute=JDAOFactory::getInstance()->getDAORoute();
			$id=$daoRoute->saveRoute($this->_route);
			$this->_route->setId($id);
			
			$daoFTRoute=FTDAOFactory::getInstance()->getDAORoute();
			$daoFTRoute->saveRoute($this->_route);
			
			
			$this->addCreateRouteSocialActivity($this->_route);
			return $this->_route->getId();
		}
		
		
		function saveRouteFromRequestJoin(){
	
			//Se lee la primera ruta
			$daoJRoute=JDAOFactory::getInstance()->getDAORoute();
			$this->_route1=$daoJRoute->getRoute(JRequest::getVar('r1Id', null));
			
			//Se lee la segunda ruta
			$daoJRoute=JDAOFactory::getInstance()->getDAORoute();
			$this->_route2=$daoJRoute->getRoute(JRequest::getVar('r2Id', null));
			
			//En caso de que tengamos el punto 3 tambien lo recogemos
			
			if (JRequest::getVar('r3Id', null) != null){
	
				$daoJRoute=JDAOFactory::getInstance()->getDAORoute();
			    $this->_route4=$daoJRoute->getRoute(JRequest::getVar('r3Id', null));
				$this->_r3=true;
			}
			
			
			//Se recoge el punto de la primera ruta clickado
			$this->_route1Click=JRequest::getVar('r1LatLong', null);
			$route1ClickLatLong = explode(",", $this->_route1Click);
			$route1ClickLat=(substr ($route1ClickLatLong[0], 1));
			$route1ClickLong=(substr ($route1ClickLatLong[1],0, -1));
			
			//Se recoge el punto de la segunda ruta clickado
			$this->_route2Click=JRequest::getVar('r2LatLong', null);
			$route2ClickLatLong = explode(",", $this->_route2Click);
			$route2ClickLat=(substr ($route2ClickLatLong[0], 1));
			$route2ClickLong=(substr ($route2ClickLatLong[1],0, -1));

			//Si ha llegado el 3  punto se recoge tambien
			
			if ($this->_r3 == true){
			$this->_route4Click=JRequest::getVar('r3LatLong', null);
			$route4ClickLatLong = explode(",", $this->_route4Click);
			$route4ClickLat=(substr ($route4ClickLatLong[0], 1));
			$route4ClickLong=(substr ($route4ClickLatLong[1],0, -1));
			}
			

			//Acortar inicio de R1 con coordenada cercana al click	
			$coordinatesArray=$this->_route1->getRawCoordinates();
			$coordinatesArray=(substr ($coordinatesArray,0, -27));
			$coordinatesArray=(substr ($coordinatesArray,25));
		
			$coordinatesSplit = explode(" ", $coordinatesArray);
			
				//Obtenemos cada coordenada partida con este formato lat,long
				$minDistan=90000;
				foreach($coordinatesSplit as $coordenadatoken){
				
				//Se separa la Longitud y la latitud para proceder a la suma
				
				/*
				 * EN LA FUSION TABLES LA LONG Y LA LAT PARECEN IR ALREVÉS
				 */
				 
				$coordenadaPartida = explode(",", $coordenadatoken);
		
					$calculo=(abs ($coordenadaPartida[1]-$route1ClickLat)) + (abs ($coordenadaPartida[0]-$route1ClickLong));
					
					 if( $calculo < $minDistan){
					 	$minDistan=$calculo;
						$r1CoorIniLat=$coordenadaPartida[1];
						$r1CoorIniLong=$coordenadaPartida[0];
					 }
			 	}
				
				//Se corta la ruta (ruta,lat,long,quitar inicio)
				$ruta1cortada=$this->cutRoute($this->_route1,$r1CoorIniLat,$r1CoorIniLong,0);
				
		   
			
			//Acortar inicio de R2 con coordenada cercana al click	
			$coordinatesArray=$this->_route2->getRawCoordinates();
			$coordinatesArray=(substr ($coordinatesArray,0, -27));
			$coordinatesArray=(substr ($coordinatesArray,25));
		
			$coordinatesSplit = explode(" ", $coordinatesArray);
			
				//Obtenemos cada coordenada partida con este formato lat,long
				$minDistan=90000;
				
				foreach($coordinatesSplit as $coordenadatoken){
				$coordenadaPartida = explode(",", $coordenadatoken);
				 
					//Se hace la consulta
					$calculo=(abs ($coordenadaPartida[1]-$route2ClickLat)) + (abs ($coordenadaPartida[0]-$route2ClickLong));
					
					 if( $calculo < $minDistan){
					 	$minDistan=$calculo;
						$r2CoorIniLat=$coordenadaPartida[1];
						$r2CoorIniLong=$coordenadaPartida[0];
					 }
			 	}
				
				//Se corta la ruta 2 (ruta,lat,long,quitar inicio)
				$ruta2cortada=$this->cutRoute($this->_route2,$r2CoorIniLat,$r2CoorIniLong,1);
				$ruta2cortadaAlreves=$this->cutRoute($this->_route2,$r2CoorIniLat,$r2CoorIniLong,0);
				
				
				
				//se consige la ruta resultante del corte entre las 2
			
			    $this->_interseccion =0;
				$joinCoordinates=$this->getJoinRoute($ruta1cortada,$ruta2cortada,$route2ClickLong);
				if ($this->_interseccion == 0)
					$joinCoordinates=$this->getJoinRoute($ruta1cortada,$ruta2cortadaAlreves,$route2ClickLong);
			
				

				$joinCoordinates=(substr ($joinCoordinates,0, -2));
				
				//Si hemos recibido un tercer punto tenemos que volver a llamar a la función
				//*************
				if ($this->_r3 == true){
					
				//Acortar inicio de R3 con coordenada cercana al click	
				$coordinatesArray=$this->_route4->getRawCoordinates();
			    $coordinatesArray=(substr ($coordinatesArray,0, -27));
			    $coordinatesArray=(substr ($coordinatesArray,25));
		
			    $coordinatesSplit = explode(" ", $coordinatesArray);
			
				//Obtenemos cada coordenada partida con este formato lat,long
				$minDistan=90000;
				
				foreach($coordinatesSplit as $coordenadatoken){
					$coordenadaPartida = explode(",", $coordenadatoken);
		
					$calculo=(abs ($coordenadaPartida[1]-$route4ClickLat)) + (abs ($coordenadaPartida[0]-$route4ClickLong));
					
					 if( $calculo < $minDistan){
					 	$minDistan=$calculo;
						$r4CoorIniLat=$coordenadaPartida[1];
						$r4CoorIniLong=$coordenadaPartida[0];
					 }
			 	}
				
				//Se corta la ruta (ruta,lat,long,quitar inicio)
				$ruta4cortada=$this->cutRoute($this->_route4,$r4CoorIniLat,$r4CoorIniLong,1);
				$ruta4cortadaAlreves=$this->cutRoute($this->_route4,$r4CoorIniLat,$r4CoorIniLong,0);
				
				//se consige la ruta resultante del corte entre las 2
			
			    $this->_interseccion =0;
				$joinCoordinates3=$this->getJoinRoute($ruta2cortada,$ruta4cortada,$route4ClickLong);
				if ($this->_interseccion == 0)
					$joinCoordinates3=$this->getJoinRoute($ruta2cortada,$ruta4cortadaAlreves,$route4ClickLong);
			    if ($this->_interseccion == 0)
					$joinCoordinates3=$this->getJoinRoute($ruta2cortadaAlreves,$ruta4cortada,$route4ClickLong);
				if ($this->_interseccion == 0)
					$joinCoordinates3=$this->getJoinRoute($ruta2cortadaAlreves,$ruta4cortadaAlreves,$route4ClickLong);

				$joinCoordinates3=(substr ($joinCoordinates3,0, -2));
					
				$joinCoordinates = $joinCoordinates.$joinCoordinates3;
					
				}

				
				//*************
					
			
				if ($joinCoordinates <> 0){
				
			    //Una vez obtenida la ruta se  le carga la información y se guarda
			    			   
			    $this->_route3=DTOFactory::getInstance()->getDTORouteFromJoin(JRequest::getVar('routeName', 'Nombre de ruta'),JRequest::getVar('routeDesc', 'Descrición de ruta'),$joinCoordinates);
			
			    $daoRoute=JDAOFactory::getInstance()->getDAORoute();
				$id=$daoRoute->saveRoute($this->_route3);
				$this->_route3->setId($id);
				
				$daoFTRoute=FTDAOFactory::getInstance()->getDAORoute();
				$daoFTRoute->saveRoute($this->_route3);
				
				
				$this->addCreateRouteSocialActivity($this->_route3);
				
				return $this->_route3->getId();
				
				}
		}

		 public function cutRoute($ruta,$lat,$long,$inicioFin)
		{
			
			$incluir=0;
			$cadena ="";
			$coordinatesArray=$ruta->getRawCoordinates();
			$coordinatesArray=(substr ($coordinatesArray,0, -27));
			$coordinatesArray=(substr ($coordinatesArray,25));

			$coordinatesSplit = explode(" ", $coordinatesArray);
				foreach($coordinatesSplit as $coordenadatoken){
						$coordenadaPartida = explode(",", $coordenadatoken);
					
						//Si queremos quitarle el inicio
						if ( $inicioFin == 0){
							
								if($coordenadaPartida[1] == $lat && $coordenadaPartida[0] == $long)
									$incluir=1;
								
								if ($incluir == 1)
									$cadena= $cadena.$coordenadaPartida[0].",".$coordenadaPartida[1]." ";
		
						}else{
							    if ($incluir == 0)
								$cadena= $cadena.$coordenadaPartida[0].",".$coordenadaPartida[1]." ";
								
								if($coordenadaPartida[1] == $lat && $coordenadaPartida[0] == $long )
									$incluir=1;
						}
				}
			return ($cadena);
			
		}

		 public function getJoinRoute($ruta1,$ruta2,$r2clik)
		{
			
			//Se van a calcular la intersección de la ruta en caso de que exista
			$ini=0;$ini2=0;$cadena="";$fin=0;$kont=0;$kont2=0;$alreves=0;
			
			
			$coordinatesSplit = explode(" ", $ruta1);
				foreach($coordinatesSplit as $coordenadatoken){
						$kont = 0;
						$coordenadaPartida = explode(",", $coordenadatoken);
							
							if ($ini==0){
								$A0=$coordenadaPartida[0];//longitud
								$A1=$coordenadaPartida[1];//latitud
								$ini=1;}
							else {
								$B0=$coordenadaPartida[0];//longitud
								$B1=$coordenadaPartida[1];//Latitud
									
								$coordinatesSplit2 = explode(" ", $ruta2);
								foreach($coordinatesSplit2 as $coordenadatoken2){ 
										$coordenadaPartida2 = explode(",", $coordenadatoken2);
											
											if ($ini2==0){
												$C0=$coordenadaPartida2[0];//longitud
												$C1=$coordenadaPartida2[1];//latitud
												$ini2=1;}
											else {
												if ($fin==0){
														$D0=$coordenadaPartida2[0];//longitud
														$D1=$coordenadaPartida2[1];//Latitud
														
														$Cruce=$this->interseccion ($A0,$A1,$B0,$B1,$C0,$C1,$D0,$D1);

														if ($Cruce <> 0){
														
														  //ha habido intersección hay que meter la intersección y a partir de hay la ruta 2
								
														  $inter = explode(",", $Cruce);
														  $cadena=$this->añadirCoordenada ($cadena,$A0,$A1);
														  $cadena=$this->añadirCoordenada ($cadena,$inter[0],$inter[1]);
														  $fin=1;
														  $this->_interseccion=1;
														  if ($r2clik > $inter[0])
														 	  $cadena=$this->añadirCoordenada ($cadena,$D0,$D1);
														  else {
									
															  $cadena=$this->añadirCoordenadaAlreves ($cadena,$ruta2,$C0,$C1);
															  return $cadena;
															  
														  }
														  
														  }
										
										
														$kont = $kont +1;
														$C0=$D0;
								        				$C1=$D1;								
												}
												else 
													
														$cadena=$this->añadirCoordenada ($cadena,$coordenadaPartida2[0],$coordenadaPartida2[1]);
												
											}
								}
								
								if ($fin == 1)
									return $cadena;
							    else{
	
							    	$cadena=$this->añadirCoordenada ($cadena,$A0,$A1);
								
								$A0=$B0;
						        $A1=$B1;
									
								}
												
							}					
				}
			
			//No ha habido intersecciones
			return $cadena;
		}


		
        public function interseccion ($A0,$A1,$B0,$B1,$C0,$C1,$D0,$D1)
        {
        	
       
		/*
		 * Ejemplo de puntos
		 * 
		 * A(2,1) B(11,-1) C(0,4) D(7,5)
		 * 
		 * ($A0 ,$A1) + t($B0-$A0 , $B1-$A1) = ($C0,$C1) + s($D0-$C0,$D1-$C1);
		 * 
		 * 2,1 + (9,-2)t = 0,4 + (7,1)
		 * 
		 * $A0 + $B0t-$A0t , $A1 + $B1t-$A1t = $C0 + $D0s-$C0s , $C1+ $D1s-$C1s
		 * 
		 * 2 + 9t , 1 -2t = 0 + 7s, 4 +1s
		 * 
		 * 2+9t=7s
		 * 1-2t=4+s
		 * 
		 * 	//las ecuaciones
		
			$A0 + $B0t-$A0t = $C0 + $D0s-$C0s 
		
			$A1 + $B1t-$A1t =  $C1+ $D1s-$C1s
		 * 
		 * 
		 * 
		 */
		
		//Metodo de la sustitucion
		
		//AX-BY=C
		//DX-EY=F
	 
	    $v1=$B0-$A0;
		$v2=$B1-$A1;
		$v3=$D0-$C0;
		$v4=$D1-$C1;
		$v5=$A0-$C0;
		$v6=$A1-$C1;
	 
	    $Y = ($v1*$v6 - $v5*$v2) / ($v1*$v4 - $v3*$v2);
		$X= (-$v6 +($v4 * $Y)) / $v2;
		
		
		//Se calcula el punto de la intersección
					
		$c1=$A0 + $X*($B0-$A0);
		$c2=$A1 + $X*($B1-$A1);
				
		//hay que valorar si el punto esta dentro del segmento o no
		if (min($B0,$A0)<=$c1 && $c1<=max($B0,$A0) && min($B1,$A1)<=$c2 && $c2<=max($B1,$A1) && min($C0,$D0)<=$c1 && $c1<=max($C0,$D0) && min($C1,$D1)<=$c2 && $c2<=max($D1,$D1))
			return ($c1.",".$c2);	
		else
			return 0;
			
        }



	    public function añadirCoordenadaAlreves ($cadena,$ruta2,$C0,$C1)
		{
			
			$kont=0;
			$coordinatesSplit2 = explode(" ", $ruta2);
			
			while ($coordinatesSplit2[$kont] <> $C0.",".$C1 )
			  $kont=$kont+1;
			
			for ($i=$kont; $i >=0 ; $i--) { 
				$coordenadaPartida2 = explode(",", $coordinatesSplit2[$i]);
				$cadena = $cadena.$coordenadaPartida2[0].",".$coordenadaPartida2[1]." ";
			}
			return $cadena ;
			
		}


		public function añadirCoordenada($cadena,$long,$lat)
		{
			if ($lat <> "" && $long <> "")
				return($cadena.$long.",".$lat." ");
			else 
				return $cadena;
			
		}
		
		public function saveRouteFromUpload(){
			$this->_route=DTOFactory::getInstance()->getDTORouteFromUpload();
			
			$daoRoute=JDAOFactory::getInstance()->getDAORoute();
			$id=$daoRoute->saveRoute($this->_route);
			$this->_route->setId($id);
			
			$daoFTRoute=FTDAOFactory::getInstance()->getDAORoute();
			$daoFTRoute->saveRoute($this->_route);
			
			$this->addUploadRouteSocialActivity($this->_route);
			return $this->_route->getId();
		}
		
		function addUserRoute(){
			$routeID=JRequest::getVar('id',0);
			$userID =& JFactory::getUser()->get('id');

			$daoUserRoutes=JDAOFactory::getInstance()->getDAOUserRoutes();
			return $daoUserRoutes->addUserRoute($routeID,$userID);
		}
		
		function removeUserRoute(){
			$routeID=JRequest::getVar('id',0);
			$userID =& JFactory::getUser()->get('id');
			
			$daoUserRoutes=JDAOFactory::getInstance()->getDAOUserRoutes();
			return $daoUserRoutes->removeUserRoute($routeID,$userID);
		}
		
		function getRouteComments(){
			$daoComments=JDAOFactory::getInstance()->getDAORouteComment();
			$routeComments=$daoComments->getRouteComments($this->_route->getId());

			return $routeComments;
		}
		
		function addRouteComment(){
			$daoComments=JDAOFactory::getInstance()->getDAORouteComment();
			return $daoComments->saveComment();
		}
		
		function downloadRoute(){
			$parser=new SRParserKML2GPX();
			header("Content-type: text/plain");
  			header("Content-Disposition: attachment; filename=".$this->_route->getName().".gpx");
  			echo $parser->KML2GPX($this->_route->getRawCoordinates(),$this->_route->getElevation());
		}
	
		
		function getRoute()
		{	
			return $this->_route;
		}
		
		function getMyRoutesTask($route){
			if($this->getIsCreator($route)){
				return DTOFactory::getInstance()->getDTOMyRoutesTaskCreador($route);
			}
			else{
				$isMyRoute=$this->getIsMyRoute($route);
				if($isMyRoute){
					return DTOFactory::getInstance()->getDTOMyRoutesTaskRemove($route);
				}
				else{
					return DTOFactory::getInstance()->getDTOMyRoutesTaskAdd($route);
				}
			}
		}
	}
?>